package parser

import (
	"fmt"
	"strconv"
	"strings"
)

// DataType 表示数据类型
type DataType struct {
	Name      string
	Size      []int  // 类型大小参数，如VARCHAR(255)
	Precision int    // 精度（用于DECIMAL等）
	Scale     int    // 标度（用于DECIMAL等）
	ArrayDims int    // 数组维度
	Nullable  bool   // 是否可为空
}

// 基本数据类型常量
var (
	IntegerType   = &DataType{Name: "INTEGER", Nullable: true}
	BigIntType    = &DataType{Name: "BIGINT", Nullable: true}
	SmallIntType  = &DataType{Name: "SMALLINT", Nullable: true}
	DecimalType   = &DataType{Name: "DECIMAL", Nullable: true}
	NumericType   = &DataType{Name: "NUMERIC", Nullable: true}
	RealType      = &DataType{Name: "REAL", Nullable: true}
	DoubleType    = &DataType{Name: "DOUBLE PRECISION", Nullable: true}
	VarcharType   = &DataType{Name: "VARCHAR", Nullable: true}
	CharType      = &DataType{Name: "CHAR", Nullable: true}
	TextType      = &DataType{Name: "TEXT", Nullable: true}
	BooleanType   = &DataType{Name: "BOOLEAN", Nullable: true}
	DateType      = &DataType{Name: "DATE", Nullable: true}
	TimeType      = &DataType{Name: "TIME", Nullable: true}
	TimestampType = &DataType{Name: "TIMESTAMP", Nullable: true}
	UnknownType   = &DataType{Name: "UNKNOWN", Nullable: true}
)

// TypeInferenceEngine 类型推断引擎
type TypeInferenceEngine struct {
	analyzer *SemanticAnalyzer
}

// NewTypeInferenceEngine 创建新的类型推断引擎
func NewTypeInferenceEngine(analyzer *SemanticAnalyzer) *TypeInferenceEngine {
	return &TypeInferenceEngine{
		analyzer: analyzer,
	}
}

// InferExpressionType 推断表达式的类型
func (tie *TypeInferenceEngine) InferExpressionType(expr Expression) *DataType {
	switch e := expr.(type) {
	case *Literal:
		return tie.inferLiteralType(e)
	case *ColumnRef:
		return tie.inferColumnRefType(e)
	case *BinaryExpr:
		return tie.inferBinaryExprType(e)
	case *UnaryExpr:
		return tie.inferUnaryExprType(e)
	case *FunctionCall:
		return tie.inferFunctionCallType(e)
	case *CaseExpr:
		return tie.inferCaseExprType(e)
	case *SubqueryExpr:
		return tie.inferSubqueryType(e)
	case *InExpr:
		return BooleanType
	case *BetweenExpr:
		return BooleanType
	case *ExistsExpr:
		return BooleanType
	default:
		return UnknownType
	}
}

// inferLiteralType 推断字面量类型
func (tie *TypeInferenceEngine) inferLiteralType(literal *Literal) *DataType {
	switch literal.Type {
	case IntegerLiteral:
		// 根据值的大小选择合适的整数类型
		if valueStr, ok := literal.Value.(string); ok {
			if val, err := strconv.ParseInt(valueStr, 10, 32); err == nil {
				if val >= -32768 && val <= 32767 {
					return SmallIntType
				}
				return IntegerType
			}
		}
		return BigIntType
	case FloatLiteral:
		return DoubleType
	case StringLiteral:
		return TextType
	case BooleanLiteral:
		return BooleanType
	case NullLiteral:
		return UnknownType // NULL的类型需要根据上下文推断
	default:
		return UnknownType
	}
}

// inferColumnRefType 推断列引用类型
func (tie *TypeInferenceEngine) inferColumnRefType(columnRef *ColumnRef) *DataType {
	// 从符号表中查找列的类型信息
	symbol := tie.analyzer.CurrentScope.LookupSymbol(columnRef.Column)
	if symbol != nil && symbol.Type == ColumnSymbol {
		return tie.parseDataType(symbol.DataType)
	}
	
	// 如果有表名，尝试从表模式中查找
	if columnRef.Table != "" {
		table := tie.analyzer.GetTable(columnRef.Table)
		if table != nil {
			if column, exists := table.Columns[columnRef.Column]; exists {
				return tie.parseDataType(column.DataType)
			}
		}
	}
	
	return UnknownType
}

// inferBinaryExprType 推断二元表达式类型
func (tie *TypeInferenceEngine) inferBinaryExprType(expr *BinaryExpr) *DataType {
	leftType := tie.InferExpressionType(expr.Left)
	rightType := tie.InferExpressionType(expr.Right)
	
	switch expr.Operator {
	case EQ, NE, LT, LE, GT, GE, LIKE, ILIKE:
		// 比较操作符总是返回布尔类型
		return BooleanType
	case AND, OR:
		// 逻辑操作符总是返回布尔类型
		return BooleanType
	case IS_NULL, IS_NOT_NULL:
		// IS NULL和IS NOT NULL操作符总是返回布尔类型
		return BooleanType
	case PLUS, MINUS, MULTIPLY, DIVIDE:
		// 算术操作符需要类型提升
		return tie.promoteNumericTypes(leftType, rightType)
	case MODULO:
		// 取模操作返回整数类型
		if tie.isIntegerType(leftType) && tie.isIntegerType(rightType) {
			return tie.promoteIntegerTypes(leftType, rightType)
		}
		return IntegerType
	case CONCAT:
		// 字符串连接操作符返回文本类型
		return TextType
	default:
		return UnknownType
	}
}

// inferUnaryExprType 推断一元表达式类型
func (tie *TypeInferenceEngine) inferUnaryExprType(expr *UnaryExpr) *DataType {
	operandType := tie.InferExpressionType(expr.Operand)
	
	switch expr.Operator {
	case NOT:
		return BooleanType
	case MINUS_UNARY, PLUS_UNARY:
		// 一元加减保持操作数的数值类型
		if tie.isNumericType(operandType) {
			return operandType
		}
		return IntegerType
	default:
		return UnknownType
	}
}

// inferFunctionCallType 推断函数调用类型
func (tie *TypeInferenceEngine) inferFunctionCallType(funcCall *FunctionCall) *DataType {
	funcName := strings.ToUpper(funcCall.Name)
	
	switch funcName {
	// 聚合函数
	case "COUNT":
		return BigIntType
	case "SUM":
		if len(funcCall.Args) > 0 {
			argType := tie.InferExpressionType(funcCall.Args[0])
			if tie.isNumericType(argType) {
				return argType
			}
		}
		return DecimalType
	case "AVG":
		return DecimalType
	case "MIN", "MAX":
		if len(funcCall.Args) > 0 {
			return tie.InferExpressionType(funcCall.Args[0])
		}
		return UnknownType
	
	// 字符串函数
	case "UPPER", "LOWER", "TRIM", "LTRIM", "RTRIM":
		return TextType
	case "LENGTH", "CHAR_LENGTH", "CHARACTER_LENGTH":
		return IntegerType
	case "SUBSTRING", "SUBSTR":
		return TextType
	
	// 数学函数
	case "ABS":
		if len(funcCall.Args) > 0 {
			argType := tie.InferExpressionType(funcCall.Args[0])
			if tie.isNumericType(argType) {
				return argType
			}
		}
		return DecimalType
	case "ROUND", "CEIL", "CEILING", "FLOOR":
		return DecimalType
	case "SQRT", "EXP", "LN", "LOG":
		return DoubleType
	
	// 日期时间函数
	case "NOW", "CURRENT_TIMESTAMP":
		return TimestampType
	case "CURRENT_DATE":
		return DateType
	case "CURRENT_TIME":
		return TimeType
	case "EXTRACT":
		return IntegerType
	
	// 类型转换函数
	case "CAST":
		// CAST函数的返回类型需要从第二个参数推断
		// 这里简化处理，实际需要解析类型参数
		return UnknownType
	
	default:
		// 未知函数，尝试从函数定义中查找
		return UnknownType
	}
}

// inferCaseExprType 推断CASE表达式类型
func (tie *TypeInferenceEngine) inferCaseExprType(caseExpr *CaseExpr) *DataType {
	// CASE表达式的类型是所有WHEN子句结果类型的公共超类型
	var resultType *DataType
	
	for _, whenClause := range caseExpr.WhenList {
		clauseType := tie.InferExpressionType(whenClause.Result)
		if resultType == nil {
			resultType = clauseType
		} else {
			resultType = tie.findCommonType(resultType, clauseType)
		}
	}
	
	// 考虑ELSE子句
	if caseExpr.Else != nil {
		elseType := tie.InferExpressionType(caseExpr.Else)
		if resultType == nil {
			resultType = elseType
		} else {
			resultType = tie.findCommonType(resultType, elseType)
		}
	}
	
	if resultType == nil {
		return UnknownType
	}
	return resultType
}

// inferSubqueryType 推断子查询类型
func (tie *TypeInferenceEngine) inferSubqueryType(subquery *SubqueryExpr) *DataType {
	// 子查询的类型取决于其SELECT列表
	// 如果只有一列，返回该列的类型
	// 如果有多列，这通常是错误的（除非在特定上下文中）
	if subquery.Select != nil {
		if len(subquery.Select.Targets) == 1 {
			return tie.InferExpressionType(subquery.Select.Targets[0])
		}
	}
	return UnknownType
}

// 类型兼容性和转换方法

// isNumericType 检查是否为数值类型
func (tie *TypeInferenceEngine) isNumericType(dataType *DataType) bool {
	switch dataType.Name {
	case "INTEGER", "BIGINT", "SMALLINT", "DECIMAL", "NUMERIC", "REAL", "DOUBLE PRECISION":
		return true
	default:
		return false
	}
}

// isIntegerType 检查是否为整数类型
func (tie *TypeInferenceEngine) isIntegerType(dataType *DataType) bool {
	switch dataType.Name {
	case "INTEGER", "BIGINT", "SMALLINT":
		return true
	default:
		return false
	}
}

// isStringType 检查是否为字符串类型
func (tie *TypeInferenceEngine) isStringType(dataType *DataType) bool {
	switch dataType.Name {
	case "VARCHAR", "CHAR", "TEXT":
		return true
	default:
		return false
	}
}

// promoteNumericTypes 数值类型提升
func (tie *TypeInferenceEngine) promoteNumericTypes(left, right *DataType) *DataType {
	// 类型提升规则：SMALLINT -> INTEGER -> BIGINT -> DECIMAL -> REAL -> DOUBLE
	typeRank := map[string]int{
		"SMALLINT":        1,
		"INTEGER":         2,
		"BIGINT":          3,
		"DECIMAL":         4,
		"NUMERIC":         4,
		"REAL":            5,
		"DOUBLE PRECISION": 6,
	}
	
	leftRank := typeRank[left.Name]
	rightRank := typeRank[right.Name]
	
	if leftRank == 0 || rightRank == 0 {
		return DecimalType // 默认返回DECIMAL
	}
	
	if leftRank >= rightRank {
		return left
	}
	return right
}

// promoteIntegerTypes 整数类型提升
func (tie *TypeInferenceEngine) promoteIntegerTypes(left, right *DataType) *DataType {
	typeRank := map[string]int{
		"SMALLINT": 1,
		"INTEGER":  2,
		"BIGINT":   3,
	}
	
	leftRank := typeRank[left.Name]
	rightRank := typeRank[right.Name]
	
	if leftRank == 0 || rightRank == 0 {
		return IntegerType
	}
	
	if leftRank >= rightRank {
		return left
	}
	return right
}

// findCommonType 查找两个类型的公共超类型
func (tie *TypeInferenceEngine) findCommonType(type1, type2 *DataType) *DataType {
	// 如果类型相同，直接返回
	if type1.Name == type2.Name {
		return type1
	}
	
	// 如果其中一个是UNKNOWN，返回另一个
	if type1.Name == "UNKNOWN" {
		return type2
	}
	if type2.Name == "UNKNOWN" {
		return type1
	}
	
	// 数值类型之间的转换
	if tie.isNumericType(type1) && tie.isNumericType(type2) {
		return tie.promoteNumericTypes(type1, type2)
	}
	
	// 字符串类型之间的转换
	if tie.isStringType(type1) && tie.isStringType(type2) {
		return TextType // 统一为TEXT类型
	}
	
	// 其他情况返回TEXT（最通用的类型）
	return TextType
}

// parseDataType 解析数据类型字符串
func (tie *TypeInferenceEngine) parseDataType(typeStr string) *DataType {
	typeStr = strings.ToUpper(strings.TrimSpace(typeStr))
	
	switch {
	case strings.HasPrefix(typeStr, "INTEGER") || typeStr == "INT":
		return IntegerType
	case strings.HasPrefix(typeStr, "BIGINT"):
		return BigIntType
	case strings.HasPrefix(typeStr, "SMALLINT"):
		return SmallIntType
	case strings.HasPrefix(typeStr, "DECIMAL") || strings.HasPrefix(typeStr, "NUMERIC"):
		return DecimalType
	case strings.HasPrefix(typeStr, "REAL"):
		return RealType
	case strings.HasPrefix(typeStr, "DOUBLE"):
		return DoubleType
	case strings.HasPrefix(typeStr, "VARCHAR"):
		return VarcharType
	case strings.HasPrefix(typeStr, "CHAR"):
		return CharType
	case strings.HasPrefix(typeStr, "TEXT"):
		return TextType
	case strings.HasPrefix(typeStr, "BOOLEAN") || strings.HasPrefix(typeStr, "BOOL"):
		return BooleanType
	case strings.HasPrefix(typeStr, "DATE"):
		return DateType
	case strings.HasPrefix(typeStr, "TIME"):
		return TimeType
	case strings.HasPrefix(typeStr, "TIMESTAMP"):
		return TimestampType
	default:
		return UnknownType
	}
}

// CheckTypeCompatibility 检查类型兼容性
func (tie *TypeInferenceEngine) CheckTypeCompatibility(sourceType, targetType *DataType) bool {
	// 相同类型总是兼容的
	if sourceType.Name == targetType.Name {
		return true
	}
	
	// UNKNOWN类型与任何类型兼容
	if sourceType.Name == "UNKNOWN" || targetType.Name == "UNKNOWN" {
		return true
	}
	
	// 数值类型之间的兼容性
	if tie.isNumericType(sourceType) && tie.isNumericType(targetType) {
		return true
	}
	
	// 字符串类型之间的兼容性
	if tie.isStringType(sourceType) && tie.isStringType(targetType) {
		return true
	}
	
	// 特殊兼容性规则
	compatibilityRules := map[string][]string{
		"INTEGER":  {"SMALLINT", "BIGINT", "DECIMAL", "NUMERIC"},
		"BIGINT":   {"INTEGER", "SMALLINT", "DECIMAL", "NUMERIC"},
		"SMALLINT": {"INTEGER", "BIGINT", "DECIMAL", "NUMERIC"},
		"TEXT":     {"VARCHAR", "CHAR"},
		"VARCHAR":  {"TEXT", "CHAR"},
		"CHAR":     {"TEXT", "VARCHAR"},
	}
	
	if compatibleTypes, exists := compatibilityRules[sourceType.Name]; exists {
		for _, compatibleType := range compatibleTypes {
			if targetType.Name == compatibleType {
				return true
			}
		}
	}
	
	return false
}

// String 返回数据类型的字符串表示
func (dt *DataType) String() string {
	result := dt.Name
	
	if len(dt.Size) > 0 {
		sizes := make([]string, len(dt.Size))
		for i, size := range dt.Size {
			sizes[i] = fmt.Sprintf("%d", size)
		}
		result += "(" + strings.Join(sizes, ", ") + ")"
	}
	
	for i := 0; i < dt.ArrayDims; i++ {
		result += "[]"
	}
	
	return result
}